package com.huluobo.lib_base

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File

/**
 *  Created by LC on 2025/6/24.
 *  下载工具
 */
object DownloadUtils {
    //url 下载地址
    //file 是通过下载之后,产生的文件
    fun download(url: String, file: File): Flow<UIState> {
        return flow {
            //通过url和OkHttp的Request构建一个网络请求
            val request = Request.Builder().url(url).get().build()

            //执行网络请求并产生一个返回(response)
            val response = OkHttpClient.Builder().build().newCall(request).execute()

            if (response.isSuccessful) {
                //网络请求成功
                //let response.body中产生值或者产生变化的时候,类似观察者模式
                response.body.let { body ->
                    file.outputStream().let { os ->
                        //从body中取出字节流,也就是下载的内容
                        val bs = body?.byteStream()
                        //文件长度或者叫字节长度,也是一个下标
                        var len = 0
                        //声明字节数组,默认DEFAULT_BUFFER_SIZE 默认缓冲区大小
                        val byteArray = ByteArray(DEFAULT_BUFFER_SIZE)

                        //  len = it!! 将渠道的字节长度的下标赋值给len
                        //循环条件判断字节的下标不等于-1,也就是判断字节数组的最后一位是否有值,如果没有值证明读取完毕,跳出循环
                        while (bs?.read(byteArray).also {
                                len = it!!
                            } != -1) {
                            //把下载的内容写入到文件中,通过outputStream写入,0代表偏移量
                            os.write(byteArray, 0, len)
                        }
                        //写入完毕,不再进入循环的时候,刷新流,确保将缓冲区的数据都写入到目标文件中
                        os.flush()
                        //关闭流,不关闭会造成内存泄漏
                        os.close()
                        emit(UIState.OnSuccess("下载成功", StateType.DOWNLOAD))
                    }
                }
            } else {
                //网络请求失败
                emit(UIState.OnError("下载失败"))
            }
        }
    }
}